home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
emmpas.zip
/
ASEMS.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-01-04
|
28KB
|
656 lines
{$O+,F+} { Allow Overlays }
{$R-} { No range checking }
{$S-} { No stack checking }
{$I-} { No I/O checking }
{$V-} { No string checking }
{$B-} { Boolean short circuit evaluation }
{$N-} { No numeric coprocessor }
{$D-} { No debug information }
Unit ASEMS; { Unit name to include in the uses clause of your program }
(*┌────────────────────────────────────────────────────────────────────────┐
│┌ base address If you have 256K of LIM EMS │
│└┬─────────────────┐ ┌─────────────────┐ the logical pages will be │
│ │ physical page 0 ├──┤ logical page 0 │ numbered 0 through - number │
│ ├─────────────────┤ ├─────────────────┤ that you allocate. When you │
│ │ physical page 1 ├──┤ logical page 1 │ specify an address in EMS │
│ ├─────────────────┤ ├─────────────────┤ you are actually addressing │
│ │ physical page 2 ├──┤ logical page 2 │ an area in the physical page │
│ ├─────────────────┤ ├─────────────────┤ array, and you will access │
│ │ physical page 3 ├──┤ logical page 3 │ any variables in the logical │
│ └──┬──────────────┘ ├─────────────────┤ pages that are currently │
│ │ │ logical page 4 │ mapped to that array. In this│
│ In the 3.2 LIM the ├─────────────────┤ example physical pages 0 - 3 │
│ physical pages are │ logical page 5 │ are mapped to logical 0 - 3. │
│ located in the 1Byte ├─────────────────┤ If you wish to access data │
│ of address space │ logical page 6 │ structures larger than 64K, │
│ allowed by the ├─────────────────┤ you need to remap to other │
│ microprocessor and │ logical page 7 │ logical pages. In the demo │
│ above the 640K ├─────────────────┤ program, 8 logical pages 0 - 7│
│ boundary. The │ logical page 8 │ are allocated and a 128K │
│ Address of the ├─────────────────┤ array of 80 character strings │
│ physical page array │ logical page 9 │ is allocated to EMS memory. │
│ is dependent on the ├─────────────────┤ │
│ hardware. │ logical page 10 │ │
│ MapAndTestPages will ├─────────────────┤ │
│ return the base │ logical page 11 │ │
│ address of the ├─────────────────┤ │
│ physical page array. │ logical page 12 │ │
│ ├─────────────────┤ │
│ │ logical page 13 │ │
│ ├─────────────────┤ │
│ │ logical page 14 │ │
│ ├─────────────────┤ │
│ │ logical page 15 │ │
│ ├─────────────────┤ │
│ │ logical page 16 │ │
│ └─────────────────┘ │
└────────────────────────────────────────────────────────────────────────┘*)
(*┌──────────────────────────────────────────────────────────────────────────┐
│ This is all you really need to use EMS memory for dynamically allocated │
│ variables. Function 15 adds storage of mapping context which you can │
│ do in a case statement with the Remap function. If you wish to write │
│ programs for wide usage then it is best to keep with 3.2 compatibility │
│ since it is a subset of the 4.0 standard. Turbo Pascal already has │
│ facility for executing code in EMS memory. You may need to add 4.0 calls│
│ if you wish to swap memory regions between an EMS page mapping context │
│ and the heap within conventional memory. │
└──────────────────────────────────────────────────────────────────────────┘*)
INTERFACE
USES CRT, DOS;
TYPE
Str3 = STRING [ 03 ];
Str55 = STRING [ 55 ];
Str5 = STRING [ 05 ];
CONST
LIMInterrupt = $67; { EMM services INTR }
DosInterrupt = $21; { DOS services INTR }
GetStatus = $40; { EMS 3.2 function 1 }
GetPageFrame = $41; { EMS 3.2 function 2 }
GetUnallocatedPageCount = $42; { EMS 3.2 function 3 }
AllocatePages = $43; { EMS 3.2 function 4 }
MapPages = $44; { EMS 3.2 function 5 }
DeAllocatePages = $45; { EMS 3.2 function 6 }
GetVersion = $46; { EMS 3.2 function 7 }
SavePageMap = $47; { EMS 3.2 function 8 }
RestorePageMap = $48; { EMS 3.2 function 9 }
GetHandleCount = $4B; { EMS 3.2 function 12 }
GetHandlePages = $4C; { EMS 3.2 function 13 }
StatusOk = 0; { EMS 3.2 status }
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION: HexString ( Number : WORD ) : Str5; │
│ │
│PURPOSE: Converts a word value : Number to a 5 character string which │
│is the return value of the function. │
│DESCRIPTION: Parses number for each character in the string and │
│appends characters to the output string. │
│INPUT: A word value. │
│OUTPUT: A five character string which can be displayed. │
└────────────────────────────────────────────────────────────────────────┘*)
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION: LIMInstalled : BOOLEAN; │
│PURPOSE: Tests for presence of EMM │
│DESCRIPTION: Checks to see if EMM is installed by looking for the │
│string 'EMMXXXX0', which is located 10 bytes from the beginning of the │
│code segment pointed to by the LIM interrupt $67 │
│OUTPUT: BOOLEAN, TRUE if installed │
└────────────────────────────────────────────────────────────────────────┘*)
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION: EMMVersion ( VAR VersionStr : Str3 ) : WORD; │
│ │
│PURPOSE: Return the Version number as a 3 character string and │
│the function value returns the error code │
│ │
│OUTPUT: Version String and errorcode │
└────────────────────────────────────────────────────────────────────────┘*)
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION : EMMError ( ErrorNumber : WORD ) : Str55; │
│PURPOSE: To find an error string from a error number │
│INPUT: Error number as a word │
│OUTPUT: Error string of type Str55 │
└────────────────────────────────────────────────────────────────────────┘*)
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION: MapAndTestPages ( NumberOfPages, L1, L2, L3, L4 : WORD; │
│ VAR Handle, Address : WORD; │
│ VAR Error : Str55 ) : BOOLEAN; │
│PURPOSE: This is a complex function which tests for the presence of │
│LIM EMS memory and then for the version. If the version is 3.2 or above│
│and sufficient pages exist for the request, NumberOfPages are allocated │
│and then physical pages 0, 1, 2, 3 are mapped to logical pages L1, L2, │
│L3, and L4 as specified by the user. The function returns a handle │
│and the address of the base of the page physical page frame. The │
│function will return FALSE if any of the requests fail and an error │
│string of type Str55 will be returned. │
│INPUT: The number of 16K pages you are requesting, the four logical │
│pages you are mapping the four physical pages to. │
│OUTPUT: An assigned handle and the base segment address of the physical│
│page frame. If there is an error the function will return false and │
│an error string of type Str55 will be passed to the calling program. │
└────────────────────────────────────────────────────────────────────────┘*)
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION: ReleaseHandle ( Handle : WORD; VAR Error : Str55 ) : BOOLEAN; │
│ │
│PURPOSE: Release EMS memory for the specified handle. │
│INPUT: Handle │
│OUTPUT: If not successful: returns error string of type Str55 and the │
│function returns FALSE │
└────────────────────────────────────────────────────────────────────────┘*)
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION: Remap ( L1, L2, L3, L4, Handle : WORD; VAR Error : Str55 ) : │
│ BOOLEAN; │
│PURPOSE: Used to remap physical pages 0 - 3 to the specified logical │
│pages. │
│INPUT: Numbers of the four logical pages and handle. │
│OUTPUT: Returns FALSE if not successful and an error string of type │
│Str55. │
└────────────────────────────────────────────────────────────────────────┘*)
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION: SaveMap ( Handle : WORD; VAR Error : Str55 ) : BOOLEAN; │
│PURPOSE: Saves the context of the present page map for later restore. │
│INPUT: Handle │
│OUTPUT: Returns FALSE if unsuccessful and an error string of type Str55│
└────────────────────────────────────────────────────────────────────────┘*)
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION: RestoreMap ( Handle : WORD; VAR Error : Str55 ) : BOOLEAN; │
│PURPOSE: Restores the context of the page map. │
│INPUT: Handle │
│OUTPUT: Returns FALSE if unsuccessful and an error string of type Str55│
└────────────────────────────────────────────────────────────────────────┘*)
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION: HandleCount( VAR Number : WORD; VAR Error : Str55 ) : BOOLEAN;│
│PURPOSE: Returns the number of handles in use by EEM. │
│INPUT: NONE │
│OUTPUT: Returns FALSE if unsuccessful and an error string of type Str55│
│Passes to the calling program the number of handle in use. │
└────────────────────────────────────────────────────────────────────────┘*)
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION: HandleCount( VAR Handle, Number : WORD; VAR Error : Str55 ) │
│ : BOOLEAN;│
│PURPOSE: Returns the number of pages in use by the specified handle. │
│INPUT: Handle │
│OUTPUT: Returns FALSE if unsuccessful and an error string of type Str55│
│Passes to the calling program the number of pages used by handle. │
└────────────────────────────────────────────────────────────────────────┘*)
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION: GetMappingSize( VAR Bytes : WORD; VAR Error : Str55 ) │
│ : BOOLEAN;│
│PURPOSE: Returns the number of bytes required for the page mapping. │
│INPUT: NONE │
│OUTPUT: Returns FALSE if unsuccessful and an error string of type Str55│
│Passes to the calling program the number bytes required to save mapping.│
└────────────────────────────────────────────────────────────────────────┘*)
(*┌────────────────────────────────────────────────────────────────────────┐
│FUNCTION: GetMap ( VAR Seg, Ofs : WORD; VAR Error : Str55 ) │
│ : BOOLEAN;│
│PURPOSE: Gets the present page mapping and outputs the array to the │
│address given in the ES:DI pair. │
│INPUT: ES:DI pointer to mapping array. │
│OUTPUT: Returns FALSE if unsuccessful and an error string of type Str55│
│Passes to the calling program the mapping area address. │
└────────────────────────────────────────────────────────────────────────┘*)
FUNCTION MapAndTestPages
( NumberofPages, L1, L2, L3, L4 : WORD; VAR Handle, Address : WORD;
VAR Error : Str55 ) : BOOLEAN;
FUNCTION ReleaseHandle ( Handle : WORD; VAR Error : Str55 ) : BOOLEAN;
FUNCTION HexString ( Number : WORD ): Str5;
FUNCTION EMMVersion ( VAR VersionStr : Str3 ) : WORD;
FUNCTION ReMap ( L1, L2, L3, L4, Handle : WORD; VAR Error : Str55 ) : BOOLEAN;
FUNCTION SaveMap ( Handle : WORD; VAR Error : Str55 ) : BOOLEAN;
FUNCTION RestoreMap ( Handle : WORD; VAR Error : Str55 ) : BOOLEAN;
FUNCTION HandleCount ( VAR Number : WORD; VAR Error : Str55 ) : BOOLEAN;
FUNCTION HandlePages ( VAR Handle, Number : WORD; VAR Error : Str55 ) : BOOLEAN;
FUNCTION GetMappingSize ( Bytes : WORD; VAR Error : Str55 ) : BOOLEAN;
IMPLEMENTATION
FUNCTION HexString ( Number : WORD ): Str5;
FUNCTION HexChar ( Number: Word ): CHAR;
BEGIN
IF Number < 10 THEN
HexChar := CHAR ( Number + 48 )
ELSE
HexChar := CHAR ( Number + 55 );
END;
VAR
S : Str5;
BEGIN
S := '';
S := HexChar ( ( Number SHR 1 ) DIV 2048 );
Number := ( ( ( Number SHR 1 ) MOD 2048 ) SHL 1 ) +
( Number AND 1 ) ;
S := S + HexChar ( Number DIV 256 );
Number := Number MOD 256;
S := S + HexChar ( Number DIV 16 );
Number := Number MOD 16;
S := S + HexChar ( Number );
HexString := S + 'h';
END;
FUNCTION LIMInstalled : BOOLEAN;
VAR
TestName : STRING [ 8 ];
DeviceName : STRING [ 8 ];
Position : WORD;
Regs : REGISTERS;
BEGIN
DeviceName := '';
TestName := 'EMMXXXX0';
WITH Regs DO
BEGIN
AH := $35; { Dos call $35 Get Interrupt Vector }
AL := LIMInterrupt;
INTR ( DosInterrupt, Regs );
Position := Regs.ES;
{ The ES register pair contains the segment address of ISR 67h }
{ Find string at position pointed to by the ES pair }
FOR Position := 0 to 7 DO
DeviceName := DeviceName + CHR ( MEM [ ES : Position + $0A ] );
LIMInstalled := TRUE; { Set BOOLEAN TRUE before test }
END;
{ Is it the EMM manager signature, 'EMMXXXX0'? then EMM is
installed and ready for use, if not, then the EMM manager
is not present }
IF DeviceName <> TestName THEN LIMInstalled := FALSE;
END;
FUNCTION EMMVersion ( VAR VersionStr : Str3 ) : WORD;
VAR
Regs : REGISTERS;
Major,
Minor : CHAR;
BEGIN
Regs.AH := GetVersion;
INTR ( LimInterrupt, Regs );
EMMVersion := Regs.AH;
IF Regs.AH = StatusOk THEN
BEGIN
Major := CHAR ( Regs.AL SHR 4 + 48 );
Minor := CHAR ( Regs.AL AND $F + 48 );
VersionStr := Major + '.' + Minor;
END;
END;
FUNCTION EMMError ( ErrorNumber: WORD ) : Str55;
BEGIN
EMMError := '';
CASE ErrorNumber OF
$80 : EMMError := 'EMM driver software failure';
$81 : EMMError := 'EMM driver detected hardware failure';
$82 : EMMError := 'EMM driver busy';
$83 : EMMError := 'Cannot find the specified handle';
$84 : EMMError := 'Undefined function code';
$85 : EMMError := 'No handles are currently available';
$86 : EMMError := 'Mapping context restoration error ';
$87 : EMMError := 'Insufficient total pages for request';
$88 : EMMError := 'Insufficient unallocated pages';
$89 : EMMError := 'Zero logical pages have been requested';
$8A : EMMError := 'Logical page out of range for handle';
$8B : EMMError := 'Physical Page out of range';
$8C : EMMError := 'Mapping register context area is full';
$8D : EMMError := 'Stack has context associated with handle';
$8E : EMMError := 'Stack has no context associated with handle';
$8F : EMMError := 'Undefined subfunction request';
$90 : EMMError := 'Attribute type undefined';
$91 : EMMError := 'System does not support nonvolatility';
$92 : EMMError := 'Partial source overwrite during move';
$93 : EMMError := 'EMS region too big for handle';
$94 : EMMError := 'Conventional and EMS memory region overlap';
$95 : EMMError := 'Offset in logical page exceeds limit';
$96 : EMMError := 'Region exceeds 1 MByte limit';
$97 : EMMError := 'Src and Dest EMS regions use same handle/overlap';
$98 : EMMError := 'Undefined memory source and destination types';
$9A : EMMError := 'Specified alternate map register set not extant';
$9B : EMMError := 'All alternate map/DMA register sets in use';
$9C : EMMError := 'Alternate map/DMA register sets not supported';
$9D : EMMError := 'Alternate map/DMA not defined, allocated or is current';
$9E : EMMError := 'Dedicated DMA channels are not supported';
$9F : EMMError := 'Dedicated DMA channel not extant';
$A0 : EMMError := 'No handle found for handle name';
$A1 : EMMError := 'A handle by that name exists';
$A2 : EMMError := 'Attempt to wrap around the 1Mbyte space during move';
$A3 : EMMError := 'Contents of user structure passed was corrupt';
$A4 : EMMError := 'Operating system denied access to function';
END;
END;
FUNCTION MapAndTestPages
( NumberofPages, L1, L2, L3, L4 : WORD; VAR Handle, Address : WORD;
VAR Error : Str55 ) : BOOLEAN;
VAR
Regs : REGISTERS;
EMMVer : Str3;
VerOk : BOOLEAN;
ValueStr : STRING;
StatsTest : WORD;
code : INTEGER;
RealVer : REAL;
BEGIN
Error := '';
MapAndTestPages := TRUE;
IF NOT LimInstalled THEN
BEGIN
MapAndTestPages := FALSE;
Error := 'LIM Expanded Memory Manager not installed';
END;
IF LimInstalled THEN
BEGIN
VerOk := FALSE;
StatsTest := EMMVersion ( EMMVer );
IF StatsTest <> StatusOk THEN
BEGIN
MapAndTestPages := FALSE;
Error := EMMError ( StatsTest );
END;
IF StatsTest = StatusOk THEN
BEGIN
ValueStr := EMMVer;
VAL ( ValueStr, RealVer, code );
IF ( RealVer < 3.1 ) THEN
BEGIN
MapAndTestPages := FALSE;
Error := 'LIM EMM version earlier than 3.2';
END;
IF ( RealVer >= 3.1 ) THEN
BEGIN
Regs.AH := GetStatus;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
MapAndTestPages := FALSE;
Error := EMMError ( Regs.AH );
END;
IF Regs.AH = StatusOk THEN
BEGIN
Regs.AH := GetUnallocatedPageCount;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
MapAndTestPages := FALSE;
Error := EMMError ( Regs.AH );
END;
IF ( Regs.AH = StatusOk ) AND ( Regs.BX < NumberOfPages ) THEN
MapAndTestPages := FALSE;
IF ( Regs.AH = StatusOk ) AND ( Regs.BX >= NumberOfPages ) THEN
BEGIN
Regs.AH := AllocatePages;
Regs.BX := NumberOfPages;
INTR ( LIMInterrupt, Regs );
Handle := Regs.DX;
IF Regs.AH <> StatusOk THEN
BEGIN
MapAndTestPages := FALSE;
Error := EMMError ( Regs.AH );
END;
IF Regs.AH = StatusOk THEN
BEGIN
Regs.AH := MapPages;
Regs.AL := 0; { Physical Page }
Regs.BX := L1; { Logical Page }
Regs.DX := Handle;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
MapAndTestPages := FALSE;
Error := EMMError ( Regs.AH );
END;
IF Regs.AH = StatusOk THEN
BEGIN
Regs.AH := MapPages;
Regs.AL := 1;
Regs.BX := L2;
Regs.DX := Handle;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
MapAndTestPages := FALSE;
Error := EMMError ( Regs.AH );
END;
IF Regs.AH = StatusOk THEN
BEGIN
Regs.AH := MapPages;
Regs.AL := 2;
Regs.BX := L3;
Regs.DX := Handle;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
MapAndTestPages := FALSE;
Error := EMMError ( Regs.AH );
END;
IF Regs.AH = StatusOk THEN
BEGIN
Regs.AH := MapPages;
Regs.AL := 3;
Regs.BX := L4;
Regs.DX := Handle;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
MapAndTestPages := FALSE;
Error := EMMError ( Regs.AH );
END;
IF Regs.AH = StatusOk THEN
BEGIN
Regs.AH := GetPageFrame;
INTR ( LIMInterrupt, Regs );
Address := Regs.BX;
END;
END;
END;
END;
END;
END;
END;
END;
END;
END;
END;
FUNCTION ReleaseHandle ( Handle : WORD; VAR Error : Str55 ) : BOOLEAN;
VAR
Regs : REGISTERS;
BEGIN
ReleaseHandle := TRUE;
Regs.AH := DeallocatePages;
Regs.DX := Handle;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
ReleaseHandle := FALSE;
Error := EMMError ( Regs.AH );
END;
END;
FUNCTION ReMap ( L1, L2, L3, L4, Handle : WORD; VAR Error : Str55 ) : BOOLEAN;
VAR
Regs : REGISTERS;
BEGIN
Remap := TRUE;
Regs.AH := MapPages;
Regs.AL := 0; { Physical Page }
Regs.BX := L1; { Logical Page }
Regs.DX := Handle;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
Remap := FALSE;
Error := EMMError ( Regs.AH );
END;
IF Regs.AH = StatusOk THEN
BEGIN
Regs.AH := MapPages;
Regs.AL := 1;
Regs.BX := L2;
Regs.DX := Handle;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
Remap := FALSE;
Error := EMMError ( Regs.AH );
END;
IF Regs.AH = StatusOk THEN
BEGIN
Regs.AH := MapPages;
Regs.AL := 2;
Regs.BX := L3;
Regs.DX := Handle;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
Remap := FALSE;
Error := EMMError ( Regs.AH );
END;
IF Regs.AH = StatusOk THEN
BEGIN
Regs.AH := MapPages;
Regs.AL := 3;
Regs.BX := L4;
Regs.DX := Handle;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
Remap := FALSE;
Error := EMMError ( Regs.AH );
END;
END;
END;
END;
END;
FUNCTION SaveMap ( Handle : WORD; VAR Error : Str55 ) : BOOLEAN;
VAR
Regs : REGISTERS;
BEGIN
SaveMap := TRUE;
Regs.AH := SavePageMap;
Regs.DX := Handle;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
SaveMap := FALSE;
Error := EMMError ( Regs.AH );
END;
END;
FUNCTION RestoreMap ( Handle : WORD; VAR Error : Str55 ) : BOOLEAN;
VAR
Regs : REGISTERS;
BEGIN
RestoreMap := TRUE;
Regs.AH := RestorePageMap;
Regs.DX := Handle;
INTR ( LIMInterrupt, Regs );
IF Regs.AH <> StatusOk THEN
BEGIN
RestoreMap := FALSE;
Error := EMMError ( Regs.AH );
END;
END;
FUNCTION HandleCount ( VAR Number : WORD; VAR Error : Str55 ) : BOOLEAN;
VAR
Regs : REGISTERS;
BEGIN
HandleCount := TRUE;
Regs.AH := GetHandleCount;
INTR ( LIMInterrupt, Regs );
Number := Regs.BX;
IF Regs.AH <> StatusOk THEN
BEGIN
HandleCount := FALSE;
Error := EMMError ( Regs.AH );
END;
END;
FUNCTION HandlePages ( VAR Handle, Number : WORD; VAR Error : Str55 ) : BOOLEAN;
VAR
Regs : REGISTERS;
BEGIN
HandlePages := TRUE;
Regs.AH := GetHandlePages;
Regs.DX := Handle;
INTR ( LIMInterrupt, Regs );
Number := Regs.BX;
IF Regs.AH <> StatusOk THEN
BEGIN
HandlePages := FALSE;
Error := EMMError ( Regs.AH );
END;
END;
FUNCTION GetMappingSize ( Bytes : WORD; VAR Error : Str55 ) : BOOLEAN;
VAR
Regs : REGISTERS;
BEGIN
GetMappingSize := TRUE;
Regs.AX := $4E03;
INTR ( LIMInterrupt, Regs );
Bytes := Regs.AX;
IF Regs.AH <> StatusOk THEN
BEGIN
GetMappingSize := FALSE;
Error := EMMError ( Regs.AH );
END;
END;
FUNCTION GetMap ( VAR Seg, Ofs: WORD; VAR Error : Str55 ) : BOOLEAN;
VAR
Regs : REGISTERS;
BEGIN
GetMap := TRUE;
Regs.AX := $4E00;
INTR ( LIMInterrupt, Regs );
Regs.ES := Seg;
Regs.Di := Ofs;
IF Regs.AH <> StatusOk THEN
BEGIN
GetMap := FALSE;
Error := EMMError ( Regs.AH );
END;
END;
END.